const { User } = require('../models')
const redisClient = require('../config/redis')
const logger = require('../utils/logger')

class SyncService {
  /**
   * 同步用户数据到所有端
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 同步结果
   */
  async syncUserData(userId) {
    try {
      const user = await User.findByPk(userId, {
        attributes: { exclude: ['password'] }
      })

      if (!user) {
        throw new Error('用户不存在')
      }

      // 构建同步数据
      const syncData = {
        id: user.id,
        phone: user.phone,
        wechat_openid: user.wechat_openid,
        nickname: user.nickname,
        avatar_url: user.avatar_url,
        gender: user.gender,
        city: user.city,
        points: user.points,
        member_level: user.member_level,
        invite_code: user.invite_code,
        status: user.status,
        last_sync_at: new Date(),
        updated_at: user.updated_at
      }

      // 存储同步数据到Redis，用于跨端数据一致性检查
      const syncKey = `user_sync:${userId}`
      await redisClient.setEx(syncKey, 24 * 60 * 60, JSON.stringify(syncData)) // 24小时过期

      // 记录同步日志
      logger.info(`用户数据同步完成: ${userId}`)

      return {
        success: true,
        data: syncData,
        syncTime: new Date()
      }
    } catch (error) {
      logger.error('用户数据同步失败:', error)
      throw error
    }
  }

  /**
   * 检查数据同步状态
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 同步状态
   */
  async checkSyncStatus(userId) {
    try {
      const syncKey = `user_sync:${userId}`
      const syncData = await redisClient.get(syncKey)

      if (!syncData) {
        return {
          synced: false,
          message: '数据未同步'
        }
      }

      const parsedData = JSON.parse(syncData)
      const user = await User.findByPk(userId)

      if (!user) {
        return {
          synced: false,
          message: '用户不存在'
        }
      }

      // 检查数据是否一致
      const isConsistent = user.updated_at.getTime() <= new Date(parsedData.updated_at).getTime()

      return {
        synced: isConsistent,
        lastSyncTime: parsedData.last_sync_at,
        message: isConsistent ? '数据已同步' : '数据需要同步'
      }
    } catch (error) {
      logger.error('检查同步状态失败:', error)
      return {
        synced: false,
        message: '检查同步状态失败'
      }
    }
  }

  /**
   * 强制同步用户数据
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 同步结果
   */
  async forceSyncUserData(userId) {
    try {
      // 清除旧的同步数据
      const syncKey = `user_sync:${userId}`
      await redisClient.del(syncKey)

      // 重新同步
      return await this.syncUserData(userId)
    } catch (error) {
      logger.error('强制同步用户数据失败:', error)
      throw error
    }
  }

  /**
   * 批量同步用户数据
   * @param {number[]} userIds - 用户ID数组
   * @returns {Promise<Object>} 批量同步结果
   */
  async batchSyncUserData(userIds) {
    try {
      const results = []
      const errors = []

      for (const userId of userIds) {
        try {
          const result = await this.syncUserData(userId)
          results.push({ userId, ...result })
        } catch (error) {
          errors.push({ userId, error: error.message })
        }
      }

      logger.info(`批量同步完成: 成功 ${results.length} 个，失败 ${errors.length} 个`)

      return {
        success: true,
        results,
        errors,
        total: userIds.length,
        successCount: results.length,
        errorCount: errors.length
      }
    } catch (error) {
      logger.error('批量同步用户数据失败:', error)
      throw error
    }
  }

  /**
   * 清理过期的同步数据
   * @returns {Promise<number>} 清理的数据条数
   */
  async cleanupExpiredSyncData() {
    try {
      const keys = await redisClient.keys('user_sync:*')
      let cleanedCount = 0

      for (const key of keys) {
        const ttl = await redisClient.ttl(key)
        if (ttl <= 0) {
          await redisClient.del(key)
          cleanedCount++
        }
      }

      if (cleanedCount > 0) {
        logger.info(`清理了 ${cleanedCount} 个过期的同步数据`)
      }

      return cleanedCount
    } catch (error) {
      logger.error('清理过期同步数据失败:', error)
      throw error
    }
  }

  /**
   * 获取用户跨端登录记录
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 登录记录
   */
  async getUserCrossPlatformLogins(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      // 从Redis获取登录记录
      const loginKey = `user_logins:${userId}`
      const loginData = await redisClient.get(loginKey)

      let logins = []
      if (loginData) {
        logins = JSON.parse(loginData)
      }

      return {
        userId,
        platforms: {
          miniprogram: user.wechat_openid ? true : false,
          h5: user.phone ? true : false
        },
        recentLogins: logins,
        lastLoginAt: user.last_login_at,
        lastLoginPlatform: user.last_login_platform
      }
    } catch (error) {
      logger.error('获取跨端登录记录失败:', error)
      throw error
    }
  }

  /**
   * 记录用户登录
   * @param {number} userId - 用户ID
   * @param {string} platform - 平台
   * @param {string} ip - IP地址
   * @returns {Promise<void>}
   */
  async recordUserLogin(userId, platform, ip) {
    try {
      const loginKey = `user_logins:${userId}`
      const loginData = await redisClient.get(loginKey)

      let logins = []
      if (loginData) {
        logins = JSON.parse(loginData)
      }

      // 添加新的登录记录
      logins.unshift({
        platform,
        ip,
        loginTime: new Date(),
        userAgent: platform === 'miniprogram' ? 'WeChat MiniProgram' : 'H5 Browser'
      })

      // 只保留最近10次登录记录
      logins = logins.slice(0, 10)

      // 存储到Redis，30天过期
      await redisClient.setEx(loginKey, 30 * 24 * 60 * 60, JSON.stringify(logins))

      // 更新用户最后登录信息
      await User.update({
        last_login_time: new Date(),
        last_login_ip: ip,
        last_login_platform: platform
      }, {
        where: { id: userId }
      })

      logger.info(`记录用户登录: ${userId} - ${platform} - ${ip}`)
    } catch (error) {
      logger.error('记录用户登录失败:', error)
    }
  }

  /**
   * 检查账户绑定状态
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 绑定状态
   */
  async checkAccountBindingStatus(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      const bindingStatus = {
        userId: user.id,
        hasPhone: !!user.phone,
        hasWechat: !!user.wechat_openid,
        hasH5Wechat: !!user.h5_openid,
        isFullyBound: !!user.phone && !!user.wechat_openid,
        bindingInfo: {
          phone: user.phone ? user.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : null,
          wechatBound: !!user.wechat_openid,
          h5WechatBound: !!user.h5_openid
        },
        accountType: this.getAccountType(user)
      }

      return bindingStatus
    } catch (error) {
      logger.error('检查账户绑定状态失败:', error)
      throw error
    }
  }

  /**
   * 获取账户类型
   * @param {Object} user - 用户对象
   * @returns {string} 账户类型
   */
  getAccountType(user) {
    if (user.phone && user.wechat_openid) {
      return 'full' // 完整账户
    } else if (user.wechat_openid) {
      return 'wechat' // 微信账户
    } else if (user.phone) {
      return 'phone' // 手机账户
    } else {
      return 'guest' // 游客账户
    }
  }

  /**
   * 同步跨端用户状态
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 同步结果
   */
  async syncCrossPlatformUserState(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      // 构建跨端状态数据
      const crossPlatformState = {
        userId: user.id,
        platforms: {
          miniprogram: {
            available: !!user.wechat_openid,
            lastLogin: user.last_login_platform === 'miniprogram' ? user.last_login_time : null
          },
          h5: {
            available: !!user.phone || !!user.h5_openid,
            lastLogin: user.last_login_platform === 'h5' ? user.last_login_time : null
          }
        },
        userState: {
          points: user.points,
          memberLevel: user.member_level,
          nickname: user.nickname,
          avatarUrl: user.avatar_url
        },
        bindingStatus: await this.checkAccountBindingStatus(userId),
        lastSyncTime: new Date()
      }

      // 存储跨端状态到Redis
      const stateKey = `cross_platform_state:${userId}`
      await redisClient.setEx(stateKey, 24 * 60 * 60, JSON.stringify(crossPlatformState))

      logger.info(`跨端用户状态同步完成: ${userId}`)

      return crossPlatformState
    } catch (error) {
      logger.error('同步跨端用户状态失败:', error)
      throw error
    }
  }

  /**
   * 获取跨端状态
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 跨端状态
   */
  async getCrossPlatformState(userId) {
    try {
      const stateKey = `cross_platform_state:${userId}`
      const stateData = await redisClient.get(stateKey)

      if (stateData) {
        return JSON.parse(stateData)
      }

      // 如果缓存中没有，重新生成
      return await this.syncCrossPlatformUserState(userId)
    } catch (error) {
      logger.error('获取跨端状态失败:', error)
      throw error
    }
  }

  /**
   * 验证数据一致性
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 一致性检查结果
   */
  async validateDataConsistency(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      const syncKey = `user_sync:${userId}`
      const syncData = await redisClient.get(syncKey)

      const consistencyResult = {
        userId,
        isConsistent: true,
        inconsistencies: [],
        lastCheckTime: new Date()
      }

      if (syncData) {
        const cachedData = JSON.parse(syncData)
        
        // 检查关键字段的一致性
        const fieldsToCheck = ['points', 'member_level', 'nickname', 'phone', 'wechat_openid']
        
        for (const field of fieldsToCheck) {
          if (user[field] !== cachedData[field]) {
            consistencyResult.isConsistent = false
            consistencyResult.inconsistencies.push({
              field,
              dbValue: user[field],
              cacheValue: cachedData[field]
            })
          }
        }
      } else {
        consistencyResult.isConsistent = false
        consistencyResult.inconsistencies.push({
          field: 'cache',
          issue: '缓存数据不存在'
        })
      }

      if (!consistencyResult.isConsistent) {
        logger.warn(`数据一致性检查失败: ${userId}`, consistencyResult.inconsistencies)
        
        // 自动修复不一致的数据
        await this.forceSyncUserData(userId)
      }

      return consistencyResult
    } catch (error) {
      logger.error('验证数据一致性失败:', error)
      throw error
    }
  }
}

module.exports = new SyncService()